"""
libclang Configuration Helper

Automatically detects and configures the libclang library path
for proper Python bindings functionality.
"""

import os
import subprocess
import sys
from pathlib import Path
from typing import Optional, List


def find_libclang_library() -> Optional[str]:
    """
    Find the libclang shared library on the system.
    
    Returns:
        Path to libclang library if found, None otherwise
    """
    # 1. Check environment variable first
    env_path = os.environ.get('LIBCLANG_PATH')
    if env_path and os.path.exists(env_path):
        return env_path
    
    # 2. Try to find using ldconfig
    try:
        result = subprocess.run(['ldconfig', '-p'], 
                              capture_output=True, text=True, timeout=10)
        if result.returncode == 0:
            for line in result.stdout.splitlines():
                if 'libclang.so' in line:
                    # Extract path from ldconfig output
                    parts = line.split(' => ')
                    if len(parts) > 1:
                        path = parts[1].strip()
                        if os.path.exists(path):
                            return path
    except (subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
        pass
    
    # 3. Check common system paths
    common_paths = [
        '/usr/lib/libclang.so',
        '/usr/lib64/libclang.so',
        '/usr/local/lib/libclang.so',
        '/usr/local/lib64/libclang.so',
        '/usr/lib/llvm/*/lib/libclang.so',
        '/usr/lib/x86_64-linux-gnu/libclang*.so',
        '/usr/lib/aarch64-linux-gnu/libclang*.so',
        '/opt/homebrew/lib/libclang.dylib',  # macOS
        '/usr/local/Cellar/llvm/*/lib/libclang.dylib',  # macOS Homebrew
    ]
    
    for pattern in common_paths:
        if '*' in pattern:
            # Handle glob patterns
            from glob import glob
            matches = glob(pattern)
            if matches:
                # Sort to prefer newer versions
                matches.sort(reverse=True)
                for match in matches:
                    if os.path.exists(match):
                        return match
        else:
            if os.path.exists(pattern):
                return pattern
    
    # 4. Try to find using package manager information
    try:
        # For Gentoo/Portage
        result = subprocess.run(['qfile', '/usr/lib*/libclang.so*'], 
                              capture_output=True, text=True, timeout=10)
        if result.returncode == 0:
            for line in result.stdout.splitlines():
                if 'libclang.so' in line:
                    path = line.strip()
                    if os.path.exists(path):
                        return path
    except (subprocess.TimeoutExpired, subprocess.SubprocessError, FileNotFoundError):
        pass
    
    # 5. Try to find in Python site-packages (bundled version)
    try:
        import clang
        clang_dir = Path(clang.__file__).parent
        possible_libs = list(clang_dir.glob('**/*libclang*'))
        for lib_path in possible_libs:
            if lib_path.is_file() and ('libclang.so' in str(lib_path) or 'libclang.dylib' in str(lib_path)):
                return str(lib_path)
    except ImportError:
        pass
    
    return None


def get_search_paths() -> List[str]:
    """Get list of paths that were searched for libclang."""
    paths = []
    
    # Environment variable
    env_path = os.environ.get('LIBCLANG_PATH')
    if env_path:
        paths.append(f"LIBCLANG_PATH: {env_path}")
    
    # Common system paths
    common_paths = [
        '/usr/lib/libclang.so',
        '/usr/lib64/libclang.so',
        '/usr/local/lib/libclang.so',
        '/usr/local/lib64/libclang.so',
        '/usr/lib/llvm/*/lib/libclang.so',
        '/usr/lib/x86_64-linux-gnu/libclang*.so',
    ]
    
    paths.extend(common_paths)
    return paths


# Global state to track configuration
_libclang_configured = None

def configure_libclang() -> bool:
    """
    Configure libclang for Python bindings.
    
    Returns:
        True if configuration was successful, False otherwise
    """
    global _libclang_configured
    
    # If we've already checked, return cached result
    if _libclang_configured is not None:
        return _libclang_configured
    
    try:
        # Try to import clang first to see if it's already working
        from clang.cindex import conf
        
        # If we can import it, try to create an Index to test
        try:
            from clang.cindex import Index
            Index.create()
            _libclang_configured = True
            return True  # Already working
        except Exception:
            pass  # Continue with configuration
        
    except ImportError:
        _libclang_configured = False
        return False  # clang module not available
    
    # Find the library
    lib_path = find_libclang_library()
    if not lib_path:
        _libclang_configured = False
        return False
    
    try:
        # Configure the library path
        from clang.cindex import conf
        conf.set_library_file(lib_path)
        
        # Test if it works
        from clang.cindex import Index
        Index.create()
        
        _libclang_configured = True
        return True
    except Exception:
        _libclang_configured = False
        return False


def get_installation_instructions() -> str:
    """Get platform-specific installation instructions for libclang."""
    
    instructions = """
To fix this issue, you need to install the libclang library:

For Gentoo Linux:
    sudo emerge sys-devel/clang

For Ubuntu/Debian:
    sudo apt-get install libclang-dev

For Fedora/RHEL:
    sudo dnf install clang-devel

For macOS (Homebrew):
    brew install llvm

For macOS (MacPorts):
    sudo port install clang

Alternative: Set LIBCLANG_PATH environment variable:
    export LIBCLANG_PATH=/path/to/libclang.so

Searched paths:
"""
    
    for path in get_search_paths():
        instructions += f"    {path}\n"
    
    return instructions


def print_libclang_status():
    """Print detailed status of libclang configuration."""
    print("🔍 libclang Configuration Status")
    print("=" * 50)
    
    # Check if clang module is available
    try:
        import clang
        print("✅ Python clang module: Available")
        print(f"   Location: {clang.__file__}")
    except ImportError:
        print("❌ Python clang module: Not found")
        print("   Run: pip install libclang")
        return
    
    # Check if we can find libclang library
    lib_path = find_libclang_library()
    if lib_path:
        print(f"✅ libclang library: {lib_path}")
    else:
        print("❌ libclang library: Not found")
        print(get_installation_instructions())
        return
    
    # Test configuration
    if configure_libclang():
        print("✅ libclang configuration: Working")
    else:
        print("❌ libclang configuration: Failed")
        print(get_installation_instructions())


if __name__ == "__main__":
    print_libclang_status()